home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / daemons / init / sysvinit.000 / sysvinit / sysvinit-2.64 / halt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-02  |  5.3 KB  |  242 lines

  1. /*
  2.  * Halt        Stop the system running.
  3.  *        It re-enables CTRL-ALT-DEL, so that a hard reboot can
  4.  *        be done. If called as reboot, it will reboot the system.
  5.  *
  6.  *        If the system is not in runlevel 0 or 6, halt will just
  7.  *        execute a "shutdown -h" to halt the system, and reboot will
  8.  *        execute an "shutdown -r". This is for compatibility with
  9.  *        sysvinit 2.4.
  10.  *
  11.  * Usage:    halt [-n] [-w] [-d] [-f]
  12.  *        -n: don't sync before halting the system
  13.  *        -w: only write a wtmp reboot record and exit.
  14.  *        -d: don't write a wtmp record.
  15.  *        -f: force halt/reboot, don't call shutdown.
  16.  *
  17.  *        Reboot and halt are both this program. Reboot
  18.  *        is just a link to halt.
  19.  *
  20.  * Author:    Miquel van Smoorenburg, miquels@drinkel.cistron.nl
  21.  *
  22.  * Version:    2.1,  16-Feb-1996
  23.  *
  24.  *        This file is part of the sysvinit suite,
  25.  *        Copyright 1991-1996 Miquel van Smoorenburg.
  26.  *
  27.  *        This program is free software; you can redistribute it and/or
  28.  *        modify it under the terms of the GNU General Public License
  29.  *        as published by the Free Software Foundation; either version
  30.  *        2 of the License, or (at your option) any later version.
  31.  */
  32.  
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <sys/param.h>
  36. #include <stdlib.h>
  37. #include <utmp.h>
  38. #include <fcntl.h>
  39. #include <string.h>
  40. #include <unistd.h>
  41. #include <sys/times.h>
  42. #include <time.h>
  43. #include <signal.h>
  44. #include <stdio.h>
  45. #include <getopt.h>
  46.  
  47. char *Version = "@(#)halt 2.1 16-Feb-1996 MvS";
  48. char *progname;
  49.  
  50. #define COMPATIBLE 1      /* For compatibility with sysvinit 2.4 */
  51. #define KERNEL_MONITOR    1 /* If halt() puts you into the kernel monitor. */
  52. #define RUNLVL_PICKY    0 /* Be picky about the runlevel */
  53.  
  54. /*
  55.  * Send usage message.
  56.  */
  57. void usage()
  58. {
  59.   fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f]\n", progname);
  60.   exit(1);
  61. }
  62.  
  63. #if COMPATIBLE
  64. /* See if we were started directly from init. */
  65.  
  66. /* Get the runlevel from /var/run/utmp. */
  67. int get_runlevel()
  68. {
  69.   FILE *fp;
  70.   struct utmp ut;
  71.   char *r;
  72. #if RUNLVL_PICKY
  73.   time_t boottime;
  74. #endif
  75.  
  76.   /* First see if we were started directly from init. */
  77.   if (getenv("INIT_VERSION") && (r = getenv("RUNLEVEL")) != NULL)
  78.     return(*r);
  79.  
  80.   /* Hmm, failed - read runlevel from /var/run/utmp.. */
  81.  
  82. #if RUNLVL_PICKY
  83.   /* Get boottime from the kernel. */
  84.   time(&boottime);
  85.   boottime -= (times(NULL) / HZ);
  86. #endif
  87.  
  88.   /* Find runlevel in utmp, */
  89.   if ((fp = fopen(UTMP_FILE, "r")) != NULL) {
  90.     while (fread(&ut, sizeof(struct utmp), 1, fp) == 1)
  91. #if RUNLVL_PICKY
  92.         /* Only accept value if it's from after boottime. */
  93.         if (ut.ut_type == RUN_LVL && ut.ut_time > boottime)
  94.             return(ut.ut_pid & 255);
  95. #else
  96.         if (ut.ut_type == RUN_LVL)
  97.             return(ut.ut_pid & 255);
  98. #endif
  99.   }
  100.   if (fp) fclose(fp);
  101.  
  102.   /* This should not happen but warn the user! */
  103.   fprintf(stderr, "WARNING: could not determine runlevel - doing hard %s\n",
  104.         progname);
  105.   fprintf(stderr, "  (it's better to use shutdown instead of %s from the command line)\n",
  106.         progname);
  107.   return(-1);
  108. }
  109.  
  110. /* Switch to another runlevel. */
  111. void do_shutdown(char *fl, char *tm)
  112. {
  113.   char *args[8];
  114.   int i = 0;
  115.  
  116.   args[i++] = "shutdown";
  117.   args[i++] = fl;
  118.   if (tm) {
  119.     args[i++] = "-t";
  120.     args[i++] = tm;
  121.   }
  122.   args[i++] = "now";
  123.   args[i++] = NULL;
  124.  
  125.   execv("/sbin/shutdown", args);
  126.   execv("/etc/shutdown", args);
  127.   execv("/bin/shutdown", args);
  128.   perror("shutdown");
  129.   exit(1);
  130. }
  131. #endif
  132.  
  133. /*
  134.  * Main program.
  135.  * Write a wtmp entry and reboot cq. halt.
  136.  */
  137. int main(argc, argv)
  138. int argc;
  139. char **argv;
  140. {
  141.   struct utmp wtmp;
  142.   int fd;
  143.   time_t t;
  144.   int do_reboot = 0;
  145.   int do_sync = 1;
  146.   int do_wtmp = 1;
  147.   int do_nothing = 0;
  148.   int do_hard = 0;
  149.   int c;
  150. #if COMPATIBLE
  151.   char *tm = NULL;
  152. #endif
  153.  
  154.   /* Find out who we are */
  155.   if ((progname = strrchr(argv[0], '/')) != NULL)
  156.       progname++;
  157.   else
  158.       progname = argv[0];
  159.       
  160.   if (geteuid() != 0) {
  161.     fprintf(stderr, "%s: must be superuser.\n", progname);
  162.     exit(1);
  163.   }
  164.  
  165.   if (!strcmp(progname, "reboot")) do_reboot = 1;
  166.  
  167.   /* Get flags */
  168.   while((c = getopt(argc, argv, ":dfnwt:")) != EOF) {
  169.     switch(c) {
  170.         case 'n':
  171.             do_sync = 0;
  172.             do_wtmp = 0;
  173.             break;
  174.         case 'w':
  175.             do_nothing = 1;
  176.             break;
  177.         case 'd':
  178.             do_wtmp = 0;
  179.             break;
  180.         case 'f':
  181.             do_hard = 1;
  182.             break;
  183. #if COMPATIBLE
  184.         case 't':
  185.             tm = optarg;
  186.             break;
  187. #endif
  188.         default:
  189.             usage();
  190.     }
  191.   }
  192.   if (argc != optind) usage();
  193.  
  194. #if COMPATIBLE
  195.   if (!do_hard && !do_nothing) {
  196.     /* See if we are in runlevel 0 or 6. */
  197.     c = get_runlevel();
  198.     if (c > '0' && c < '6')
  199.         do_shutdown(do_reboot ? "-r" : "-h", tm);
  200.   }
  201. #endif
  202.  
  203.   /* Record the fact that we're going down */
  204.   if (do_wtmp && (fd = open(WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
  205.       time(&t);
  206.       strcpy(wtmp.ut_user, "shutdown");
  207.       strcpy(wtmp.ut_line, "~");
  208.       strcpy(wtmp.ut_id,  "~~");
  209.       wtmp.ut_pid = 0;
  210.       wtmp.ut_type = RUN_LVL;
  211.       wtmp.ut_time = t;
  212.       write(fd, (char *)&wtmp, sizeof(wtmp));
  213.       close(fd);
  214.   }
  215.  
  216.   /* Exit if all we wanted to do was write a wtmp record. */
  217.   if (do_nothing) exit(0);
  218.  
  219.   if (do_sync) {
  220.     sync();
  221.     sleep(2);
  222.   }
  223.  
  224.   if (do_reboot) {
  225.     reboot(0xfee1dead, 672274793, 0x01234567);
  226.   } else {
  227.     /* Turn on hard reboot, CTRL-ALT-DEL will reboot now */
  228.     reboot(0xfee1dead, 672274793, 0x89ABCDEF);
  229.  
  230.     /* Stop init; it is insensitive to the signals sent by the kernel. */
  231.     kill(1, SIGTSTP);
  232.  
  233.     /* And perform the `halt' system call. */
  234.     reboot(0xfee1dead, 672274793, 0xCDEF0123);
  235.   }
  236.   /* If we return, we (c)ontinued from the kernel monitor. */
  237.   reboot(0xfee1dead, 672274793, 0);
  238.   kill(1, SIGCONT);
  239.  
  240.   exit(0);
  241. }
  242.